home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / dev / gui / FoxGuiSource.lha / FoxLibSource / Windows.c < prev   
C/C++ Source or Header  |  2001-07-07  |  35KB  |  1,266 lines

  1. /* FoxGUI - The fast, flexible, free Amiga GUI system
  2.     Copyright (C) 2001 Simon Fox (Foxysoft)
  3.  
  4. This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  5. Foxysoft: www.foxysoft.co.uk      Email:simon@foxysoft.co.uk                */
  6.  
  7. /******************************************************************************
  8.  * Shared library code.  Cannot call functions which use exit() such as:
  9.  * printf(), fprintf()
  10.  *
  11.  * Otherwise:
  12.  * The linker returns "__XCEXIT undefined" and the program will fail.
  13.  * This is because you must not exit() a library!
  14.  *
  15.  * Also:
  16.  * proto/exec.h must be included instead of clib/exec_protos.h and
  17.  * __USE_SYSBASE must be defined.
  18.  *
  19.  * Otherwise:
  20.  * The linker returns "Absolute reference to symbol _SysBase" and the
  21.  * library crashes.  Presumably the same is true for the other protos.
  22.  ******************************************************************************/
  23.  
  24. #define __USE_SYSBASE
  25.  
  26. #define WINDOWSC
  27.  
  28. #include <proto/mathieeedoubbas.h>
  29. #include <stdarg.h>
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #include <string.h>
  33.  
  34. #include <proto/intuition.h>
  35. #include <proto/dos.h>
  36. #include <proto/exec.h>
  37. #include <libraries/asl.h>
  38. #include <proto/asl.h>
  39. #include <dos/dosextens.h>
  40.  
  41. #include "/FoxInclude/foxgui.h"
  42. #include "FoxGuiTools.h"
  43.  
  44. #define PATH_SIZE 100
  45.  
  46. static char *DirText = "Drawer";
  47. static char *AssignText = "Assign";
  48. static BOOL VolumeList = FALSE;
  49. static ListBox    *FileList;
  50. static GuiWindow *FileWindow;
  51. static OutputBox *lblFile, *lblPath;
  52. static EditBox *FileNameBox = NULL, *PathBox = NULL;
  53. static PushButton *LoadButton, *SaveButton, *FileDoneButton, *ParentButton, *VolumesButton;
  54. static struct FileRequester *fr = NULL;
  55. static char mask[100], Path[PATH_SIZE];
  56.  
  57. static struct FileList *CreateVolumeList(void);
  58. static int VolumesFn(PushButton *pb);
  59.  
  60. void FOXLIB WriteText(REGA0 GuiWindow *gw, REGA1 char *text, REGD0 int x, REGD1 int y)
  61. {
  62.     struct IntuiText it;
  63.  
  64.     it.FrontPen = Gui.TextCol;
  65.     it.BackPen = 0;
  66.     it.DrawMode = JAM1;
  67.     it.LeftEdge = 0;
  68.     it.TopEdge = 0;
  69.     it.ITextFont = &GuiFont;
  70.     it.IText = text;
  71.     it.NextText = NULL;
  72.  
  73.     PrintIText(gw->Win->RPort, &it, x, y);
  74. }
  75.  
  76. void CloseGuiWindow(GuiWindow *w)
  77.    {
  78.    short temp = Gui.CleanupFlag;
  79.    Diagnostic("CloseGuiWindow", ENTER, TRUE);
  80.    AbortAllMessages();
  81.    if (w == Gui.GWLfirst)
  82.       Gui.GWLfirst = w->next;
  83.    else
  84.       w->previous->next = w->next;
  85.    if (w->next)
  86.       w->next->previous = w->previous;
  87.    Gui.CleanupFlag = TRUE;
  88.     ClearMenus(w);
  89.     DestroyWinTickBoxes(w, FALSE);
  90.     DestroyWinListBoxes(w, FALSE);
  91.     DestroyWinButtons(w, FALSE);
  92.     DestroyWinDDListBoxes(w, FALSE);
  93.     DestroyWinEditBoxes(w, FALSE);
  94.     DestroyWinOutputBoxes(w, FALSE);
  95.     DestroyWinTabControls(w, FALSE);
  96.     DestroyWinFrames(w, FALSE);
  97.     DestroyWinRadioButtons(w, FALSE);
  98.     WakePointer(w);
  99.    Gui.CleanupFlag = temp;
  100.     if (w->ConReadSig != 0)
  101.         {
  102.        CloseConsole(w->Con);
  103.         GuiFree(w->Con);
  104.         }
  105.    CloseWindow(w->Win);
  106.    GuiFree(w->WidgetData);
  107.    GuiFree(w);
  108.    QueueAllMessages();
  109.    Diagnostic("CloseGuiWindow", EXIT, TRUE);
  110.    }
  111.  
  112. static BOOL ICanOpenWindow(struct Screen *scr)
  113.    {
  114.    int count = 0;
  115.     GuiWindow *w = Gui.GWLfirst;
  116.    Diagnostic("ICanOpenWindow", ENTER, TRUE);
  117.  
  118.    while (w)
  119.       {
  120.       if (w->ParentScreen == scr && w->ConReadSig != 0)
  121.          count++;
  122.       w = w->next;
  123.       }
  124.     if (count > 4)
  125.       SetLastErr("Cannot open another console.");
  126.  
  127.    Diagnostic("ICanOpenWindow", EXIT, TRUE);
  128.     return (BOOL) (count < 5 && scr != NULL);
  129.    }
  130.  
  131. //static short UpDownFillPoints[24] = { 1, 1, 10, 1, 1, 2, 10, 2, 1, 3, 10, 3, 1, 4, 10, 4, 1, 5, 10, 5, 1, 6, 10, 6 };
  132. static short UpDownPoints[12] = { 0, 7, 0, 0, 10, 0, 1, 7, 11, 7, 11, 0 };
  133. static struct Border
  134. //    UDfill    = { (WORD) 0, (WORD) 0, (UBYTE) 0, (UBYTE) 2, (UBYTE) JAM1, (BYTE) 12, (WORD *) UpDownFillPoints, (struct Border *) NULL },
  135.     Udark        = { (WORD) 0, (WORD) 0, (UBYTE) 2, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) &(UpDownPoints[6]), (struct Border *) NULL /* &UDfill */},
  136.     Ulight    = { (WORD) 0, (WORD) 0, (UBYTE) 1, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) UpDownPoints, (struct Border *) &Udark },
  137.     Usdark    = { (WORD) 0, (WORD) 0, (UBYTE) 1, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) &(UpDownPoints[6]), (struct Border *) NULL /* &UDfill */},
  138.     Uslight    = { (WORD) 0, (WORD) 0, (UBYTE) 2, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) UpDownPoints, (struct Border *) &Usdark };
  139. static struct Border
  140.     Ddark        = { (WORD) 0, (WORD) 0, (UBYTE) 2, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) &(UpDownPoints[6]), (struct Border *) NULL /* &UDfill */},
  141.     Dlight    = { (WORD) 0, (WORD) 0, (UBYTE) 1, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) UpDownPoints, (struct Border *) &Ddark },
  142.     Dsdark    = { (WORD) 0, (WORD) 0, (UBYTE) 1, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) &(UpDownPoints[6]), (struct Border *) NULL /* &UDfill */},
  143.     Dslight    = { (WORD) 0, (WORD) 0, (UBYTE) 2, (UBYTE) 2, (UBYTE) JAM1, (BYTE)  3, (WORD *) UpDownPoints, (struct Border *) &Dsdark };
  144.  
  145.  
  146. /*    Although for private Gui windows, the second parameter can be derived from the first (pgs->scr), if
  147.     the screen is public, the first parameter can be NULL because this function now gets all of the screen
  148.     info it needs (apart from a pointer to the parent GuiScreen structure to copy into the GuiWindow
  149.     structure) from the second parameter. */
  150. GuiWindow *CreateGuiWindow(GuiScreen *pgs, struct Screen *Scr, int Left, int Top, int Width, int Height, int Dpen, int Bpen, char *Title, int flags, int (* __far __stdargs eventfn)(struct GWS*, int event, int x, int y, void*))
  151.    {
  152.    static long Number = 0L;
  153.    GuiWindow *c;
  154.    char name[5];
  155.    Diagnostic("CreateGuiWindow", ENTER, TRUE);
  156.     if (!Scr)
  157.       {
  158.       Diagnostic("CreateGuiWindow", EXIT, FALSE);
  159.       return NULL;
  160.       }
  161.    if ((flags & GW_CONSOLE) && !ICanOpenWindow(Scr))
  162.       {
  163.       Diagnostic("CreateGuiWindow", EXIT, FALSE);
  164.       return NULL;
  165.       }
  166.    sprintf(name, "%ld\0", ++Number);
  167.    if (!(c = (GuiWindow *) GuiMalloc(sizeof(GuiWindow), 0)))
  168.       {
  169.       Diagnostic("CreateGuiWindow", EXIT, FALSE);
  170.       return NULL;
  171.       }
  172.    if (!(c->WidgetData = (Widget *) GuiMalloc(sizeof(Widget), 0)))
  173.       {
  174.         GuiFree(c);
  175.       Diagnostic("CreateGuiWindow", EXIT, FALSE);
  176.       return NULL;
  177.       }
  178.     c->WidgetData->ObjectType = WindowObject;
  179.     c->EventFn = eventfn;
  180.     c->WidgetData->flags = flags;
  181.     c->WidgetData->NextWidget = NULL;
  182.     c->WidgetData->ChildWidget = NULL;
  183.  
  184.    c->NewWin.FirstGadget = NULL;
  185.  
  186.     c->NewWin.Screen = Scr;
  187.    c->NewWin.LeftEdge = Left;
  188.    c->NewWin.TopEdge = Top;
  189.    c->NewWin.Width = Width;
  190.    c->NewWin.Height = Height;
  191.    c->NewWin.DetailPen = Dpen;
  192.    c->NewWin.BlockPen = Bpen;
  193.    c->NewWin.Title = Title;
  194.     c->NewWin.MinWidth = Width;
  195.     c->NewWin.MinHeight = Height;
  196.     c->NewWin.MaxWidth = (unsigned short) ~0; // Allows a window as wide as the screen
  197.     c->NewWin.MaxHeight = (unsigned short) ~0; // Allows a window as high as the screen
  198.    c->NewWin.Flags = WFLG_SMART_REFRESH | WFLG_ACTIVATE | WFLG_NOCAREREFRESH;
  199.     /* The IDCMP_MOUSEMOVE flag in the IDCMPFlags below does not cause mousemove messages to be generated
  200.         for this window (WFLG_FOLLOWMOUSE in the Flags section above would do that).  IDCMP_MOUSEMOVE
  201.         merely causes any MOUSEMOVE events sent to this window to be sent as IDCMP messages.  These
  202.         MOUSEMOVE events may be sent by any gadget in the window which has GACT_FOLLOWMOUSE set in it's
  203.         activation flags - causing MOUSEMOVE events to be sent only when the gadget is active. */
  204.    c->NewWin.IDCMPFlags = GADGETUP | GADGETDOWN | MOUSEBUTTONS | INTUITICKS | MENUPICK | IDCMP_MOUSEMOVE
  205.                                     | IDCMP_RAWKEY;
  206.    if (flags & GW_DRAG)
  207.       c->NewWin.Flags |= WFLG_DRAGBAR;
  208.     if (flags & GW_BORDERLESS)
  209.         c->NewWin.Flags |= WFLG_BORDERLESS;
  210.     if (flags & GW_BACKDROP)
  211.         c->NewWin.Flags |= WFLG_BACKDROP;
  212.     if (flags & GW_DEPTH)
  213.         c->NewWin.Flags |= WFLG_DEPTHGADGET;
  214.     if (flags & GW_ACTIVE)
  215.         c->NewWin.IDCMPFlags |= IDCMP_ACTIVEWINDOW;
  216.     if (flags & GW_SIZE)
  217.         c->NewWin.Flags |= WFLG_SIZEGADGET;
  218.     if (flags & GW_SIZE || Gui.DroppingList)
  219.         c->NewWin.IDCMPFlags |= IDCMP_NEWSIZE;
  220.     if (flags & GW_DISKIN)
  221.         c->NewWin.IDCMPFlags |= IDCMP_DISKINSERTED;
  222.     if (flags & GW_DISKOUT)
  223.         c->NewWin.IDCMPFlags |= IDCMP_DISKREMOVED;
  224.     if (flags & GW_CLOSE)
  225.         {
  226.         c->NewWin.Flags |= WFLG_CLOSEGADGET;
  227.         c->NewWin.IDCMPFlags |= IDCMP_CLOSEWINDOW;
  228.         }
  229.    c->NewWin.Type = (pgs ? CUSTOMSCREEN : PUBLICSCREEN);
  230.    c->NewWin.CheckMark = NULL;
  231.    c->NewWin.BitMap = NULL;
  232.     /* Open the window using the 3D look but in a backwards compatible way
  233.         rather than using OpenWindowTags() or OpenWindowTagList() which are
  234.         simpler but not backwards compatible */
  235.     if (!(c->Win = (struct Window *) OpenWindow((struct NewWindow *) &(c->NewWin))))
  236.       {
  237.       GuiFree(c->WidgetData);
  238.       GuiFree(c);
  239.       Diagnostic("CreateGuiWindow", EXIT, FALSE);
  240.       return NULL;
  241.       }
  242.     if (flags & GW_CONSOLE)
  243.         {
  244.         if (!(c->Con = (struct Console *) GuiMalloc(sizeof(struct Console), 0)))
  245.             {
  246.           CloseWindow(c->Win);
  247.           GuiFree(c->WidgetData);
  248.           GuiFree(c);
  249.           Diagnostic("CreateGuiWindow", EXIT, FALSE);
  250.           return NULL;
  251.             }
  252.         if (!OpenConsole(c->Con, c->Win, name))
  253.           {
  254.             GuiFree(c->Con);
  255.           CloseWindow(c->Win);
  256.           GuiFree(c->WidgetData);
  257.           GuiFree(c);
  258.           Diagnostic("CreateGuiWindow", EXIT, FALSE);
  259.           return NULL;
  260.           }
  261.         }
  262.    AbortAllMessages();
  263.    c->WidgetData->Parent = pgs;
  264.     c->ParentScreen = Scr;
  265.     c->Enabled = c->OldStatus = TRUE;
  266.     c->Sleep = FALSE;
  267.     c->FirstMenu = NULL;
  268.     c->MenuFn = NULL;
  269.     if (flags & GW_CONSOLE)
  270.        c->ConReadSig = 1L << c->Con->RePort->mp_SigBit;
  271.     else
  272.         c->ConReadSig = 0;
  273.    c->WindowSig  = 1L << c->Win->UserPort->mp_SigBit;
  274.    c->previous = NULL;
  275.    c->next = Gui.GWLfirst;
  276.    if (Gui.GWLfirst)
  277.       Gui.GWLfirst->previous = c;
  278.    Gui.GWLfirst = c; 
  279.    QueueAllMessages();
  280.    Diagnostic("CreateGuiWindow", EXIT, TRUE);
  281.    return c;
  282.    }
  283.  
  284. BOOL FOXLIB SetWindowLimits(REGA0 GuiWindow *gw, REGD0 long minwidth, REGD1 long minheight, REGD2 unsigned long maxwidth, REGD3 unsigned long maxheight)
  285. {
  286.     return WindowLimits(gw->Win, minwidth, minheight, maxwidth, maxheight);
  287. }
  288.  
  289. GuiWindow* FOXLIB OpenGuiWindow(REGA0 void *Scr, REGD0 int Left, REGD1 int Top, REGD2 int Width, REGD3 int Height,
  290.         REGD4 int Dpen, REGD5 int Bpen, REGA1 char *Title, REGD6 int flags,
  291.         REGA2 int (* __far __stdargs eventfn)(GuiWindow*, int, int, int, void*), REGA3 void *extension)
  292.     {
  293.     struct Screen *PubScr;
  294.     GuiWindow *retval;
  295.  
  296.     if (!Scr)
  297.         return NULL;
  298.  
  299.     if (ISGUISCREEN(Scr))
  300.         {
  301.         GuiScreen *sc = (GuiScreen *) Scr;
  302.         return CreateGuiWindow(sc, sc->scr, Left, Top, Width, Height, Dpen, Bpen, Title, flags, eventfn);
  303.         }
  304.  
  305.     // Scr is not a FoxGui screen so it must be the name of a public screen to open on.
  306.     if (Gui.LibVersion < 36) // Public screens weren't available before release 36
  307.         return NULL;
  308.  
  309.     PubScr = LockPubScreen((char *) Scr);
  310.     if (!PubScr)
  311.         return NULL;
  312.  
  313.     retval = CreateGuiWindow(NULL, PubScr, Left, Top, Width, Height, Dpen, Bpen, Title, flags, eventfn);
  314.     /*    We can unlock the public screen now because if CreateGuiWindow() succeeded the new window will act
  315.         as a lock on the public screen and if it failed then we don't need the lock anymore anyway! */
  316.     UnlockPubScreen((char *) Scr, PubScr);
  317.     return retval;
  318.     }
  319.  
  320. void CloseAllWindows(void)
  321.    {
  322.    GuiWindow *w;
  323.    Diagnostic("CloseAllWindows", ENTER, TRUE);
  324.    while (w = Gui.GWLfirst)
  325.         CloseGuiWindow(w);
  326.    Diagnostic("CloseAllWindows", EXIT, TRUE);
  327.    }
  328.  
  329. void CloseScrWindows(GuiScreen *sc)
  330.    {
  331.    GuiWindow *w = Gui.GWLfirst, *n;
  332.    BOOL message = FALSE;
  333.    Diagnostic("CloseScrWindows", ENTER, TRUE);
  334.    while (w && sc)
  335.       {
  336.       n = w->next;
  337.       if (w->ParentScreen == sc->scr)
  338.          {
  339.          CloseGuiWindow(w);
  340.          message = TRUE;
  341.          }
  342.       w = n;
  343.       }
  344.       if (Gui.CleanupFlag && message)
  345.          SetLastErr("Screen closed with windows still open.");
  346.    Diagnostic("CloseScrWindows", EXIT, TRUE);
  347.    }
  348.  
  349. #define FNAME_LEN 40
  350. #define FS_SIZE    20
  351. #define DT_LEN        14
  352.  
  353. struct FileList
  354.     {
  355.     long type, size;
  356.     char FileName[FNAME_LEN + DT_LEN + 1];
  357.     struct DateStamp Date;
  358.     char sizestr[FS_SIZE + 1], *fns;
  359.     struct FileList *Next;
  360.     };
  361.  
  362. static int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  363.  
  364. static char *SizeToString(long size, char *str)
  365.     {
  366.     /*    On return, str contains the size right aligned within FS_SIZE spaces.  The return value is the
  367.         first non-space character in the string. */
  368.     if (str)
  369.         {
  370.         sprintf(str, "%-d", size);
  371.         return RightAlignString(str, FS_SIZE + 1, TRUE);
  372.         }
  373.     return NULL;
  374.     }
  375.  
  376. static void DateStampToString(struct DateStamp *ds, char *str)
  377.     {
  378.     if (str && ds)
  379.         {
  380.         int Day = 1, Month = 0, Year = 1978;
  381.         long days = ds->ds_Days;
  382.         int hours = ds->ds_Minute / 60;
  383.         int minutes = ds->ds_Minute % 60;
  384.         char ctemplate[24 + 1];
  385.         char tempstr[DT_LEN + 1];
  386.         str[0] = 0;
  387.         // Create the date bit
  388.         // Dates start at Jan 1st 1978
  389.         while (days > 0)
  390.             {
  391.             days--;
  392.             if (++Day > DaysInMonth[Month])
  393.                 {
  394.                 Day = 1;
  395.                 if (++Month > 11)
  396.                     {
  397.                     Month = 0;
  398.                     Year++;
  399.                     }
  400.                 if (Month == 1) // Feb (months from 0-11)
  401.                     {
  402.                     // Check for a leap year.
  403.                     if (Year % 400 == 0)
  404.                         DaysInMonth[1] = 29;
  405.                     else if (Year % 4 == 0 && Year % 40 != 0)
  406.                         DaysInMonth[1] = 29;
  407.                     else
  408.                         DaysInMonth[1] = 28;
  409.                     }
  410.                 }
  411.             }
  412.         Month++; // Now in range 1-12.
  413.         Year %= 100; // Strip off the century.
  414.         sprintf(ctemplate, "%s%%-d/%s%%-d/%s%%-d", Day < 10 ? "0" : "", Month < 10 ? "0" : "",
  415.                 Year < 10 ? "0" : "");
  416.         sprintf(tempstr, ctemplate, Day, Month, Year);
  417.         strcat(str, tempstr);
  418.         // Create the time bit
  419.         sprintf(ctemplate, " %s%%-d:%s%%-d", hours < 10 ? "0" : "", minutes < 10 ? "0" : "");
  420.         sprintf(tempstr, ctemplate, hours, minutes);
  421.         strcat(str, tempstr);
  422.         }
  423.     }
  424.  
  425. static void FreeFileList(struct FileList *fl)
  426.     {
  427.     struct FileList *nf;
  428.  
  429.     while (fl)
  430.         {
  431.         nf = fl->Next;
  432.         GuiFree(fl);
  433.         fl = nf;
  434.         }
  435.     }
  436.  
  437. static struct FileList *CreateFileList(char *dir)
  438.     {
  439.     /* Given a directory path, creates a filelist containing the names, sizes and types of all the
  440.         entries (files & directories) in that directory that match the current mask (if there is one) */
  441.  
  442.     struct FileList *FirstFile = NULL, *LastFile = NULL;
  443.     struct FileInfoBlock *Fptr = (struct FileInfoBlock *) GuiMalloc(sizeof(struct FileInfoBlock), 0);
  444.     BPTR LockPtr = Lock(dir, ACCESS_READ);
  445.  
  446.     if (LockPtr && Fptr)
  447.         {
  448.         BOOL ok;
  449.  
  450.         VolumeList = FALSE;
  451.         if (!strcmp(dir, ":"))
  452.             {
  453.             BPTR ParentPtr = ParentDir(LockPtr);
  454.             while (ParentPtr)
  455.                 {
  456.                 UnLock(LockPtr);
  457.                 LockPtr = DupLock(ParentPtr);
  458.                 UnLock(ParentPtr);
  459.                 ParentPtr = ParentDir(LockPtr);
  460.                 }
  461.             }
  462.         ok = Examine(LockPtr, Fptr);
  463.         while (ok)
  464.             {
  465.             ok = ExNext(LockPtr, Fptr);
  466.             if (ok)
  467.                 {
  468.                 BOOL addit = FALSE;
  469.  
  470.                 if (Fptr->fib_DirEntryType > 0) // Add it because it's a directory
  471.                     // It's a directory so add it to the list.
  472.                     addit = TRUE;
  473.                 else if (strcmp(mask, ""))
  474.                     {
  475.                     int ptr = strlen(Fptr->fib_FileName) - strlen(mask);
  476.                     if (ptr >= 0)
  477.                         if (!stricmp(&Fptr->fib_FileName[ptr], mask))
  478.                             addit = TRUE; // Add it because it matches the mask
  479.                     }
  480.                 else // Add it because there is no mask
  481.                     addit = TRUE;
  482.  
  483.                 if (addit)
  484.                     {
  485.                     struct FileList *fl = (struct FileList *) GuiMalloc(sizeof(struct FileList), MEMF_CLEAR);
  486.                     if (fl)
  487.                         {
  488.                         strncpy(fl->FileName, Fptr->fib_FileName, FNAME_LEN);
  489.                         memcpy(&fl->Date, &Fptr->fib_Date, sizeof(struct DateStamp));
  490.                         fl->type = Fptr->fib_DirEntryType;
  491.                         fl->size = Fptr->fib_Size;
  492.                         if (!LastFile)
  493.                             FirstFile = LastFile = fl;
  494.                         else
  495.                             {
  496.                             LastFile->Next = fl;
  497.                             LastFile = fl;
  498.                             }
  499.                         }
  500.                     } // if (addit)
  501.                 } // if (ok)
  502.             } // while (ok)
  503.         } // if (LockPtr && Fptr)
  504.     else
  505.         {
  506.         /*    The user has supplied a bad directory/device name.  Give them a DisplayBeep and a list of
  507.             volumes! */
  508.         DisplayBeep(FileWindow->ParentScreen);
  509.  
  510.         FirstFile = CreateVolumeList();
  511.         }
  512.     if (LockPtr)
  513.         UnLock(LockPtr);
  514.     if (Fptr)
  515.         GuiFree(Fptr);
  516.  
  517.     return FirstFile;
  518.     }
  519.  
  520. static BOOL DirectoryList(ListBox *lb, struct FileList *FirstFile)
  521.     {
  522.     int files = 0;
  523.     long longestfname = 0, longestsize = 0, Tab2, DigitLen;
  524.     struct IntuiText temptext;
  525.     struct FileList *cfl;
  526.  
  527.     if (!lb)
  528.         return FALSE;
  529.  
  530.     // First work out the length of an intuitext digit in this font (we'll need this later).
  531.     temptext.ITextFont = lb->Font;
  532.     temptext.NextText = NULL;
  533.     temptext.IText = "8";
  534.     DigitLen = IntuiTextLength(&temptext);
  535.  
  536.     ClearListBoxItems(lb, FALSE);
  537.  
  538.     // First loop through and find the longest
  539.     cfl = FirstFile;
  540.     while (cfl)
  541.         {
  542.         long len;
  543.  
  544.         temptext.IText = cfl->FileName;
  545.         len = IntuiTextLength(&temptext);
  546.         if (len > longestfname)
  547.             longestfname = len;
  548.         if (VolumeList && cfl->type == DLT_VOLUME)
  549.             {
  550.             files++;
  551.             cfl->sizestr[0] = 0;
  552.             temptext.IText = cfl->fns = RightAlignString(cfl->sizestr, FS_SIZE + 1, FALSE);
  553.             }
  554.         else if (cfl->type > 0)
  555.             {
  556.             strcpy(cfl->sizestr, VolumeList ? AssignText : DirText);
  557.             temptext.IText = cfl->fns = RightAlignString(cfl->sizestr, FS_SIZE + 1, FALSE);
  558.             }
  559.         else
  560.             {
  561.             files++;
  562.             temptext.IText = cfl->fns = SizeToString(cfl->size, cfl->sizestr);
  563.             }
  564.         len = IntuiTextLength(&temptext);
  565.         if (len > longestsize)
  566.             longestsize = len;
  567.         cfl = cfl->Next;
  568.         }
  569.  
  570.     // Allow room for at least 7 digits (including commas) if files are present. 6 otherwise.
  571.     longestsize = max(longestsize, (files > 0 ? 7 : 6) * DigitLen);
  572.  
  573.     longestfname += 2 * DigitLen;
  574.     Tab2 = longestfname + longestsize + 2 * DigitLen;
  575.     SetListBoxTabStops(lb, FALSE, 2, longestfname, Tab2);
  576.  
  577.     /*    Now put the whole string together and add the files to the list box (we'll add directories at
  578.         the end. */
  579.     cfl = FirstFile;
  580.     while (cfl)
  581.         {
  582.         char *size = cfl->sizestr, *fc = cfl->fns;
  583.  
  584.         strcat(cfl->FileName, "\t");
  585.         do
  586.             {
  587.             temptext.IText = fc;
  588.             fc = &fc[-1];
  589.             } while (fc >= size && IntuiTextLength(&temptext) < longestsize);
  590.         strcat(cfl->FileName, temptext.IText);
  591.         if (!VolumeList)
  592.             {
  593.             char DateStr[DT_LEN + 1];
  594.  
  595.             DateStampToString(&cfl->Date, DateStr);
  596.             if (DateStr)
  597.                 {
  598.                 strcat(cfl->FileName, "\t");
  599.                 strcat(cfl->FileName, DateStr);
  600.                 }
  601.             }
  602.         if ((cfl->type <= 0 && !VolumeList) || (VolumeList && cfl->type == DLT_VOLUME))
  603.             AddListBoxItem(lb, cfl->FileName, FALSE);
  604.         cfl = cfl->Next;
  605.         }
  606.     // Put the files in alphabetical order
  607.     if (files > 1)
  608.         SortListBox(lb, ASCENDING | IGNORE_CASE, 1, FALSE);
  609.  
  610.     // Now add the directories at the end and free the list
  611.     cfl = FirstFile;
  612.     while (cfl)
  613.         {
  614.         if ((cfl->type > 0 && !VolumeList) || (VolumeList && cfl->type == DLT_DIRECTORY))
  615.             AddListBoxItem(lb, cfl->FileName, FALSE);
  616.         cfl = cfl->Next;
  617.         }
  618.  
  619.     /*    If we've added more than one directory then sort them now by starting the sort at the first
  620.         directory. */
  621.     if (files + 1 < lb->NoItems)
  622.         SortListBox(lb, ASCENDING | IGNORE_CASE, files + 1, TRUE);
  623.     else
  624.         ListBoxRefresh(lb);
  625.  
  626.     return TRUE;
  627.     }
  628.  
  629. static BOOL IsDirText(char *text)
  630.     {
  631.     while (text[0] == ' ')
  632.         text = &text[1];
  633.     return (BOOL) (strcmp(text, DirText) == 0);
  634.     }
  635.  
  636. /* static BOOL IsVolumeText(char *text)
  637.     {
  638.     while (text[0] == ' ')
  639.         text = &text[1];
  640.     if (strcmp(text, VolumeText) == 0)
  641.         return TRUE;
  642.     else if (strcmp(text, AssignText) == 0)
  643.         return TRUE;
  644.     return FALSE;
  645.     } */
  646.  
  647. int FileListClickFn(ListBox *lb, short Event, int ItemNo, void **Data)
  648.     {
  649.     char *text = HiText(FileList); // HiText only returns the first string, in this case the directory name
  650.     struct IntuiText *HiItem = lb->HiItem;
  651.     int loop;
  652.     struct FileList *fl;
  653.  
  654.     if (Event == LB_SELECT)
  655.         {
  656.         SleepFile();
  657.         if (HiItem && HiItem->NextText && IsDirText(HiItem->NextText->IText) && HiItem->TopEdge ==
  658.                 HiItem->NextText->TopEdge)
  659.             {
  660.             if (strlen(Path) > 0 && !strchr(":/", Path[strlen(Path) - 1]))
  661.                 strcat(Path, "/");
  662.             strcat(Path, text);
  663.             // Remove trailing spaces
  664.             for (loop = ((int) strlen(Path)) - 1; loop >= 0 && Path[loop] == ' '; Path[loop--] = 0);
  665.             SetEditBoxText(PathBox, Path);
  666.             SetEditBoxText(FileNameBox, "");
  667.             fl = CreateFileList(Path);
  668.             DirectoryList(FileList, fl);
  669.             FreeFileList(fl);
  670.             }
  671.         else if (HiItem && VolumeList)
  672.             {
  673.             strcpy(Path, text);
  674.             // Remove trailing spaces
  675.             for (loop = ((int) strlen(Path)) - 1; loop >= 0 && Path[loop] == ' '; Path[loop--] = 0);
  676.             if (Path[((int) strlen(Path)) - 1] != ':')
  677.                 strcat(Path, ":");
  678.             SetEditBoxText(PathBox, Path);
  679.             SetEditBoxText(FileNameBox, "");
  680.             fl = CreateFileList(Path);
  681.             DirectoryList(FileList, fl);
  682.             FreeFileList(fl);
  683.             }
  684.         else
  685.             SetEditBoxText(FileNameBox, text);
  686.         WakeFile();
  687.         }
  688.     return GUI_CONTINUE;
  689.     }
  690.  
  691. BOOL PathValidate(EditBox *eb)
  692.     {
  693.     short retval;
  694.     struct FileList *fl;
  695.     char *ptr = GetEditBoxText(eb);
  696.     int pathlen;
  697.  
  698.     strncpy(Path, ptr, PATH_SIZE - 1);
  699.     pathlen = strlen(Path);
  700.     if (pathlen > 1)
  701.         if (Path[pathlen - 1] == '/' && !strchr("/:", Path[pathlen - 2]))
  702.             {
  703.             // Remove a trailing / from the path name.
  704.             Path[pathlen - 1] = 0;
  705.             SetEditBoxText(eb, Path);
  706.             }
  707.  
  708.     fl = CreateFileList(Path);
  709.     retval = (short) DirectoryList(FileList, fl);
  710.     FreeFileList(fl);
  711.     SetEditBoxFocus(FileNameBox);
  712.  
  713.     return retval;
  714.     }
  715.  
  716. BOOL FileNameValidate(EditBox *eb)
  717.     {
  718.     eb = eb;
  719.     return TRUE;
  720.     }
  721.  
  722. char *GetFName(void)
  723.     {
  724.     if (fr)
  725.         return fr->rf_File;
  726.     else
  727.         return GetEditBoxText(FileNameBox);
  728.     }
  729.  
  730. char *GetPath(void)
  731.     {
  732.     if (fr)
  733.         return fr->rf_Dir;
  734.     else
  735.         return GetEditBoxText(PathBox);
  736.     }
  737.  
  738. void FOXLIB SetFName(REGA0 char *fname)
  739.     {
  740.     if (FileNameBox && fname && !fr)
  741.         SetEditBoxText(FileNameBox, fname);
  742.     }
  743.  
  744. void FOXLIB SetPath(REGA0 char *path)
  745.     {
  746.     if (PathBox && path && !fr)
  747.         SetEditBoxText(PathBox, path);
  748.     }
  749.  
  750. void SleepFile(void)
  751.     {
  752.     if (!fr)
  753.         SleepPointer(FileWindow);
  754.     }
  755.  
  756. void WakeFile(void)
  757.     {
  758.     if (!fr)
  759.         {
  760.         WakePointer(FileWindow);
  761.         if (FileNameBox)
  762.             SetEditBoxFocus(FileNameBox);
  763.         }
  764.     }
  765.  
  766. void FOXLIB UpdateFList(void)
  767.     {
  768.     if (FileWindow && !fr)
  769.         {
  770.         struct FileList *fl = CreateFileList(Path);
  771.         DirectoryList(FileList, fl);
  772.         FreeFileList(fl);
  773.         }
  774.     }
  775.  
  776. static void ClearFileWindow(void)
  777.     {
  778.    DestroyWinButtons(FileWindow, FALSE);
  779.     DestroyWinEditBoxes(FileWindow, FALSE);
  780.     DestroyWinOutputBoxes(FileWindow, FALSE);
  781.     DestroyWinListBoxes(FileWindow, FALSE);
  782.     PathBox = NULL;
  783.     FileNameBox = NULL;
  784.     FileList = NULL;
  785.     }
  786.  
  787. int FileDoneButtFn(PushButton *pb)
  788.    {
  789.    pb = pb;
  790.     return GUI_MODAL_END;
  791.    }
  792.  
  793. int FileWinEventFn(GuiWindow *win, int Event, int x, int y, void *data)
  794. {
  795.     win = win;
  796.  
  797.     if (Event == GW_CLOSE)
  798.     {
  799.         /*    We have to return GUI_MODAL_END because only GUI_MODAL_END will wake up the other windows.  There's
  800.             no need to close the window, though, because that will be done after the return of winmsgloop() */
  801.         return GUI_CANCEL | GUI_MODAL_END;
  802.     }
  803.     return GUI_CONTINUE;
  804. }
  805.  
  806. int ParentFn(PushButton *pb)
  807.    {
  808.     int l;
  809.     BOOL done = FALSE, parent = FALSE;
  810.     struct FileList *fl;
  811.     struct FileInfoBlock *Fptr;
  812.     BPTR LockPtr;
  813.  
  814.     // Can't go any higher than a list of volumes!
  815.     if (VolumeList)
  816.         {
  817.         SetEditBoxFocus(FileNameBox);
  818.         return GUI_CONTINUE;
  819.         }
  820.  
  821.     SleepFile();
  822.  
  823.     // Check whether the current path has a parent.
  824.     Fptr = (struct FileInfoBlock *) malloc(sizeof(struct FileInfoBlock));
  825.     LockPtr = Lock(Path, ACCESS_READ);
  826.  
  827.     if (LockPtr && Fptr)
  828.         {
  829.         BOOL ok = Examine(LockPtr, Fptr);
  830.         if (ok)
  831.             {
  832.             BPTR ParentPtr = ParentDir(LockPtr);
  833.             if (ParentPtr)
  834.                 {
  835.                 parent = TRUE;
  836.                 UnLock(ParentPtr);
  837.                 }
  838.             }
  839.         }
  840.     if (LockPtr)
  841.         UnLock(LockPtr);
  842.     if (Fptr)
  843.         free(Fptr);
  844.  
  845.     if (!parent)
  846.         {
  847.         // The current path has no parent so leave Path unchanged and give a list of volumes.
  848.  
  849.         fl = CreateVolumeList();
  850.         DirectoryList(FileList, fl);
  851.         FreeFileList(fl);
  852.         WakeFile();
  853.  
  854.         return GUI_CONTINUE;
  855.         }
  856.  
  857.     for (l = ((int) strlen(Path)) - 1; l >= 0; l--)
  858.         if (l == ((int) strlen(Path)) - 1 && Path[l] == ':')
  859.             {
  860.             /*    The very last character is a : but we know that this directory has a parent because we
  861.                 checked (above) so this must be an assign.  Append a / to get the parent. */
  862.             strcat(Path, "/");
  863.             done = TRUE;
  864.             break;
  865.             }
  866.         else if (Path[l] == ':')
  867.             { // The path is a device name followed by a : followed by a dir name.  Remove the dir name.
  868.             memset(&Path[l + 1], 0, (PATH_SIZE - l - 1) * sizeof(char));
  869.             done = TRUE;
  870.             break;
  871.             }
  872.         else if (Path[l] == '/')
  873.             {
  874.             BOOL addslash = FALSE;
  875.  
  876.             /*    The path may be "[[device]:][directory]/[/]directory" or it may be "/" or "//" etc or it may
  877.                 be "[device]:[/]" .  If it's the former then we find the parent by removing the last
  878.                 specified directory name.  If it's any of the others then we find the parent by adding
  879.                 another "/" onto the end. */
  880.  
  881.             if (l > 0)
  882.                 {
  883.                 if (strchr(":/", Path[l - 1]))
  884.                     if (l == ((int) strlen(Path)) - 1)
  885.                         addslash = TRUE;
  886.                     else
  887.                         l++; // So that the last / or : isn't removed.
  888.                 }
  889.             else
  890.                 addslash = TRUE;
  891.  
  892.             if (!addslash)
  893.                 // Remove the last dir name
  894.                 memset(&Path[l], 0, (PATH_SIZE - l) * sizeof(char));
  895.             else
  896.                 strcat(Path, "/");
  897.             done = TRUE;
  898.             break;
  899.             }
  900.  
  901.     if (!done)
  902.         {
  903.         int l;
  904.         BOOL charfound = FALSE;
  905.  
  906.         /*    We looked right through the file name without encountering a : or a / so the path must be blank
  907.             or relative to the current directory */
  908.  
  909.         for (l = ((int) strlen(Path)) - 1; l >= 0; l--)
  910.             if (Path[l] != ' ')
  911.                 charfound = TRUE;
  912.  
  913.         // Blank the path.
  914.         memset(Path, 0, PATH_SIZE * sizeof(char));
  915.  
  916.         if (charfound)
  917.             {
  918.             // Path is a directory beneath the current.  Blanking it is sufficient to find the parent.
  919.             }
  920.         else
  921.             // Path is blank;
  922.             Path[0] = '/';
  923.         }
  924.  
  925.     SetEditBoxText(PathBox, Path);
  926.     SetEditBoxText(FileNameBox, "");
  927.  
  928.     fl = CreateFileList(Path);
  929.     DirectoryList(FileList, fl);
  930.     FreeFileList(fl);
  931.  
  932.     WakeFile();
  933.  
  934.     return GUI_CONTINUE;
  935.     }
  936.  
  937. struct TagItem FRtags[] =
  938.     {
  939.     ASL_Hail,        0L,
  940.     ASL_OKText,        0L,
  941.     ASL_CancelText,0L,
  942.     ASL_Pattern,    0L,
  943.     ASL_Window,        0L,
  944.     ASL_FuncFlags,    0L,
  945.     ASL_Height,        160,
  946.     ASL_Width,        300,
  947.     ASL_LeftEdge,    150,
  948.     ASL_TopEdge,    18,
  949.     ASL_Dir,            0L,
  950.     ASL_File,        0L,
  951.     TAG_DONE
  952.     };
  953.  
  954. #define DEVICE_NAME_LEN    255
  955.  
  956. //extern long DOSBase;
  957. static char DeviceName[DEVICE_NAME_LEN + 1];
  958.  
  959. static char *GetStr(BSTR bstr) // Takes a BSTR and converts it into a normal C str
  960.     {
  961.     int namelen;
  962.     char *stringstart;
  963.  
  964.     /*    bstr is a BSTR (a BCPL string).  These have the length stored in the first byte
  965.         and then the characters in successive following bytes but no NULL terminator. */
  966.  
  967.     stringstart = (char *) BADDR(bstr);
  968.     if (!stringstart)
  969.         return NULL;
  970.     namelen = (int) *stringstart;
  971.     stringstart = &(stringstart[1]);
  972.     strncpy(DeviceName, stringstart, min(namelen, 255));
  973.     DeviceName[min(namelen, 255)] = 0;
  974.  
  975.     return DeviceName;
  976.     }
  977.  
  978. static struct FileList *CreateVolumeList(void)
  979.     {
  980.     if (DOSBase)
  981.         {
  982.         struct RootNode *rn = ((struct DosLibrary *)DOSBase)->dl_Root;
  983.         struct DosInfo *di = NULL;
  984.         struct DeviceList *dl = NULL;
  985.         if (!rn)
  986.             SetLastErr("No RootNode.");
  987.         else
  988.             di = (struct DosInfo *) BADDR(rn->rn_Info);
  989.         if (!di)
  990.             SetLastErr("No DosInfo.");
  991.         else
  992.             {
  993.             /*    Disable multi-tasking because we're about to get the device list by illegal methods and we
  994.                 don't want intuition changing it while we're looking at it! */
  995.             Forbid();
  996.             dl = (struct DeviceList *) BADDR(di->di_DevInfo);
  997.             }
  998.         if (!dl)
  999.             {
  1000.             Permit();
  1001.             SetLastErr("No DeviceList.");
  1002.             }
  1003.         else
  1004.             {
  1005.             struct FileList *FirstDev = NULL, *LastDev = NULL;
  1006.             struct DeviceList *Dev = dl;
  1007.  
  1008.             /*    Add the volumes and assigns only.  No need to worry about late binding assigns because if
  1009.                 the OS is new enough to know about late binding assigns then it's new enough to use the
  1010.                 ASL file requester instead of this one. */
  1011.             while (Dev)
  1012.                 {
  1013.                 if (Dev->dl_Type == DLT_VOLUME || Dev->dl_Type == DLT_DIRECTORY)
  1014.                     if (GetStr(Dev->dl_Name))
  1015.                         {
  1016.                         struct FileList *f = (struct FileList *) GuiMalloc(sizeof(struct FileList), MEMF_CLEAR);
  1017.                         if (f)
  1018.                             {
  1019.                             int DevNameLen;
  1020.  
  1021.                             if (LastDev)
  1022.                                 {
  1023.                                 LastDev->Next = f;
  1024.                                 LastDev = f;
  1025.                                 }
  1026.                             else
  1027.                                 FirstDev = LastDev = f;
  1028.  
  1029.                             f->type = Dev->dl_Type;
  1030.                             if (Dev->dl_Type == DLT_DIRECTORY && strlen(DeviceName) < DEVICE_NAME_LEN)
  1031.                                 strcat(DeviceName, ":");
  1032.                             DevNameLen = strlen(DeviceName);
  1033.                             strncpy(f->FileName, DeviceName, min(FNAME_LEN, DevNameLen));
  1034.                             f->FileName[min(FNAME_LEN, DevNameLen)] = 0;
  1035.                             }
  1036.                         }
  1037.                 Dev = (struct DeviceList *) BADDR(Dev->dl_Next);
  1038.                 }
  1039.             Permit();
  1040.  
  1041.             VolumeList = TRUE;
  1042.             return FirstDev;
  1043.             }
  1044.         }
  1045.     else
  1046.         SetLastErr("No DOSBase.");
  1047.     return NULL;
  1048.     }
  1049.  
  1050. static int VolumesFn(PushButton *pb)
  1051.     {
  1052.     struct FileList *fl;
  1053.  
  1054.     pb = pb;
  1055.     SleepFile();
  1056.  
  1057.     // The Volumes button toggles between a list of volumes and the filelist for the specified path
  1058.     if (VolumeList)
  1059.         fl = CreateFileList(Path);
  1060.     else
  1061.         fl = CreateVolumeList();
  1062.     DirectoryList(FileList, fl);
  1063.     FreeFileList(fl);
  1064.     WakeFile();
  1065.  
  1066.     return GUI_CONTINUE;
  1067.     }
  1068.  
  1069. BOOL FOXLIB ShowFileRequester(REGA0 GuiWindow *Wnd, REGA1 char *path, REGA2 char *fname, REGA3 char *pattern, REGD0 char
  1070.         *title, REGD1 BOOL Save, REGD2 int (* __far __stdargs callfn) (char*, char*))
  1071.     {
  1072.     /*    The Window parameter is used to work out what screen the file requester should be shown on.  It
  1073.         shouldn't matter which window on that screen we use. */
  1074.     static BOOL firsttime = TRUE;
  1075.  
  1076.     // Store a pointer to the Window whose Screen currently recieves system requesters for this Process
  1077.     struct Window *ProcWindow = Gui.Proc->pr_WindowPtr;
  1078.  
  1079.     memset(mask, 0, sizeof(mask));
  1080.     if (path)
  1081.         {
  1082.         memset(Path, 0, sizeof(Path));
  1083.         strcpy(Path, path);
  1084.         }
  1085.     else if (firsttime)
  1086.         memset(Path, 0, sizeof(Path));
  1087.     firsttime = FALSE;
  1088.     if (pattern == NULL)
  1089.         pattern = "";
  1090.     if (fname == NULL)
  1091.         fname = "";
  1092.  
  1093.     if (AslBase = OpenLibrary("asl.library", 37L))
  1094.         {
  1095.         BOOL Okay = TRUE;
  1096.         strcpy(mask, "#?");
  1097.         strcpy(&mask[2], pattern);
  1098.         FRtags[0].ti_Data = (unsigned long) title;
  1099.         FRtags[1].ti_Data = (unsigned long) (Save ? "Save" : "Load");
  1100.         FRtags[2].ti_Data = (unsigned long) "Done";
  1101.         FRtags[3].ti_Data = (unsigned long) mask;
  1102.         FRtags[4].ti_Data = (unsigned long) Wnd->Win;
  1103.         FRtags[5].ti_Data = FILF_NEWIDCMP;    // Must set this every time to prevent the Save setting from
  1104.         if (Save)                                    // being perpetuated.
  1105.             FRtags[5].ti_Data |= FILF_SAVE;
  1106.         FRtags[10].ti_Data = (unsigned long) Path;
  1107.         FRtags[11].ti_Data = (unsigned long) fname;
  1108.  
  1109.         if (!(fr = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, FRtags)))
  1110.             {
  1111.             CloseLibrary(AslBase);
  1112.             return FALSE;
  1113.             }
  1114.  
  1115.         // Make any file error related requesters go to the current applications screen.
  1116.         Gui.Proc->pr_WindowPtr = Wnd->Win;
  1117.  
  1118.         while (Okay)
  1119.             {
  1120.             Okay = AslRequest(fr, NULL);
  1121.             strncpy(Path, GetPath(), PATH_SIZE - 2);
  1122.             Path[PATH_SIZE - 1] = 0;
  1123.             if (callfn && Okay)
  1124.                 {
  1125.                 int callfnretval = (*callfn) (GetFName(), Path);
  1126.  
  1127.                 if (callfnretval != GUI_CONTINUE)
  1128.                     Okay = FALSE;
  1129.                 }
  1130.             }
  1131.  
  1132.         // Redirect system requesters back to the screen they were previously sent to.
  1133.         Gui.Proc->pr_WindowPtr = ProcWindow;
  1134.  
  1135.         FreeAslRequest(fr);
  1136.         CloseLibrary(AslBase);
  1137.         fr = NULL;
  1138.         }
  1139.     else
  1140.         {
  1141.         struct FileList *fl;
  1142.         int twp = TopWindowPixel(Wnd->ParentScreen, NULL);
  1143.         strcpy(mask, pattern);
  1144.  
  1145.         if (!(FileWindow = CreateGuiWindow((GuiScreen*) Wnd->WidgetData->Parent, Wnd->ParentScreen, 144, 18, 312, 127 + twp, Wnd->NewWin.DetailPen, Wnd->NewWin.BlockPen, title, GW_CLOSE | GW_DRAG | GW_DEPTH | GW_SIZE, FileWinEventFn)))
  1146.             return FALSE;
  1147.  
  1148.         if (!(FileList = MakeListBox(FileWindow, 7, twp + 1, 286, 77, 2, 2, LB_SELECT | S_AUTO_SIZE, FileListClickFn, NULL)))
  1149.             {
  1150.             CloseGuiWindow(FileWindow);
  1151.             FileWindow = NULL;
  1152.             return FALSE;
  1153.             }
  1154.  
  1155.         SleepFile();
  1156.  
  1157.         lblPath            = MakeOutputBox(FileWindow, 7, twp + 82, 50, 6, 0, "Drawer", JUSTIFY_RIGHT | NO_BORDER | S_AUTO_SIZE, NULL);
  1158.         lblFile            = MakeOutputBox(FileWindow, 7, twp + 94, 50, 6, 0, "File", JUSTIFY_RIGHT | NO_BORDER | S_AUTO_SIZE, NULL);
  1159.  
  1160.         PathBox            = MakeEditBox(FileWindow, 60, twp + 82, 230, 34, 0, (void*) PathValidate, THREED | S_AUTO_SIZE | EB_CLEAR, NULL);
  1161.         FileNameBox        = MakeEditBox(FileWindow, 60, twp + 94, 230, 34, 0, FileNameValidate, THREED | S_AUTO_SIZE | EB_CLEAR, NULL);
  1162.         if (Save)
  1163.             SaveButton    = MakeFileButton(FileWindow, "_Save",    7, twp + 108, 68, 14, 's', NULL, callfn);
  1164.         else
  1165.             LoadButton    = MakeFileButton(FileWindow, "_Load",    7, twp + 108, 68, 14, 'l', NULL, callfn);
  1166.         VolumesButton    = MakeButton(FileWindow, "_Volumes", 79, twp + 108, 69, 14, 'p', NULL, VolumesFn, BN_CLEAR | BN_STD | S_AUTO_SIZE, NULL);
  1167.         ParentButton    = MakeButton(FileWindow, "_Parent", 152, twp + 108, 69, 14, 'p', NULL, ParentFn, BN_CLEAR | BN_STD | S_AUTO_SIZE, NULL);
  1168.         FileDoneButton    = MakeButton(FileWindow, "_Done",   225, twp + 108, 68, 14, 'd', NULL, FileDoneButtFn, BN_CLEAR | BN_STD | S_AUTO_SIZE, NULL);
  1169.         SetEditBoxText(PathBox, Path);
  1170.         SetEditBoxText(FileNameBox, fname);
  1171.         fl = CreateFileList(Path);
  1172.         DirectoryList(FileList, fl);
  1173.         FreeFileList(fl);
  1174.         WakeFile();
  1175.  
  1176.         // Make any file error related requesters go to the current applications screen.
  1177.         Gui.Proc->pr_WindowPtr = Wnd->Win;
  1178.  
  1179.         WinMsgLoop(FileWindow);
  1180.  
  1181.         // Redirect system requesters back to the screen they were previously sent to.
  1182.         Gui.Proc->pr_WindowPtr = ProcWindow;
  1183.  
  1184.         ClearFileWindow();
  1185.         CloseGuiWindow(FileWindow);
  1186.         }
  1187.     return TRUE;
  1188.     }
  1189.  
  1190. void FOXLIB WinPrint(REGA0 GuiWindow *w, REGA1 char *str)
  1191. {
  1192.     if (w && str)
  1193.         if (w->Con)
  1194.             ConPrint(w->Con, str);
  1195. }
  1196.  
  1197. void FOXLIB WinTab(REGA0 GuiWindow *w, REGD0 int x, REGD1 int y)
  1198. {
  1199.     if (w)
  1200.         if (w->Con)
  1201.             ConTab(w->Con, x, y);
  1202. }
  1203.  
  1204. void FOXLIB WinPrintTab(REGA0 GuiWindow *w, REGD0 int x, REGD1 int y, REGA1 char *str)
  1205. {
  1206.     if (w && str)
  1207.         if (w->Con)
  1208.             ConPrintTab(w->Con, x, y, str);
  1209. }
  1210.  
  1211. void FOXLIB WinPrintCol(REGA0 GuiWindow *w, REGA1 char *str, REGD0 int col)
  1212. {
  1213.     if (w && str)
  1214.         if (w->Con)
  1215.             ConPrintHi(w->Con, str, col);
  1216. }
  1217.  
  1218. void FOXLIB WinShowCursor(REGA0 GuiWindow *w)
  1219. {
  1220.     if (w)
  1221.         if (w->Con)
  1222.             ConShowCursor(w->Con);
  1223. }
  1224.  
  1225. void FOXLIB WinHideCursor(REGA0 GuiWindow *w)
  1226. {
  1227.     if (w)
  1228.         if (w->Con)
  1229.             ConHideCursor(w->Con);
  1230. }
  1231.  
  1232. void FOXLIB WinClear(REGA0 GuiWindow *w)
  1233. {
  1234.     if (w)
  1235.         if (w->Con)
  1236.             ConClear(w->Con);
  1237. }
  1238.  
  1239. void FOXLIB WinHome(REGA0 GuiWindow *w)
  1240. {
  1241.     if (w)
  1242.         if (w->Con)
  1243.             ConHome(w->Con);
  1244. }
  1245.  
  1246. void FOXLIB WinBlankToEOL(REGA0 GuiWindow *w)
  1247. {
  1248.     if (w)
  1249.         if (w->Con)
  1250.             ConBlankToEOL(w->Con);
  1251. }
  1252.  
  1253. void FOXLIB WinWrapOn(REGA0 GuiWindow *w)
  1254. {
  1255.     if (w)
  1256.         if (w->Con)
  1257.             ConWrapOn(w->Con);
  1258. }
  1259.  
  1260. void FOXLIB WinWrapOff(REGA0 GuiWindow *w)
  1261. {
  1262.     if (w)
  1263.         if (w->Con)
  1264.             ConWrapOff(w->Con);
  1265. }
  1266.